<template>
  <div>
    <svg width="1000" height="1500">
      <g />
      <rect />
    </svg>
  </div>
</template>

<script>
import dagreD3 from 'dagre-d3'
import * as d3 from 'd3'
export default {
  data() {
    return {
      isTipBoxShowed: false,
      list: {
        nodeInfos: [
          {
            id: 'node1',
            label: '节点1',
            shape: 'house',
          },
          {
            id: 'node2',
            label: '节点2',
            shape: 'house',
          },
          {
            id: 'node3',
            label: '节点3',
          },
          {
            id: 'node4',
            label: '节点4',
          },
          {
            id: 'node5',
            label: '节点5',
          },
          {
            id: 'node6',
            label: '节点6',
          },
        ],
        edges: [
          {
            source: 'node1',
            target: 'node2',
          },
          // 节点指向自己
          {
            source: 'node2',
            target: 'node2',
          },
          {
            source: 'node2',
            target: 'node3',
          },
          // 往回指向
          {
            source: 'node3',
            target: 'node2',
          },
          {
            source: 'node2',
            target: 'node4',
          },
          {
            source: 'node4',
            target: 'node5',
          },
          {
            source: 'node5',
            target: 'node6',
          },
          {
            source: 'node2',
            target: 'node6',
          },
          {
            source: 'node3',
            target: 'node4',
          },
          {
            source: 'node1',
            target: 'node4',
          },
          {
            source: 'node2',
            target: 'node6',
          },
        ],
      },
    }
  },
  mounted() {
    //获取D3
    var g = new dagreD3.graphlib.Graph().setGraph({})
    console.log(g)
    // 添加节点
    this.list.nodeInfos.forEach((item) => {
      item.rx = item.ry = 5 //圆角
      g.setNode(item.id, item)
    })
    // 链接关系
    this.list.edges.forEach((item) => {
      g.setEdge(item.source, item.target, {
        style: 'stroke: #0fb2cc; fill: none;',
        arrowheadStyle: 'fill: #0fb2cc;stroke: #0fb2cc;',
        arrowhead: 'hollowPoint',
      })
    })
    g.nodes().forEach(function (v) {
      console.log('Node ' + v + ': ' + JSON.stringify(g.node(v)))
    })
    g.edges().forEach(function (e) {
      console.log(
        'Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e))
      )
    })
    //绘制图形
    var svg = d3.select('svg'),
      inner = svg.select('g')
    //缩放
    var zoom = d3.zoom().on('zoom', function () {
      inner.attr('transform', d3.event.transform)
    })
    svg.call(zoom)
    var render = new dagreD3.render()
    // 在此处进行自定义节点形状和箭头类型
    render.shapes().house = function (parent, bbox, node) {
      var w = bbox.width,
        h = bbox.height,
        points = [
          { x: 0, y: 0 },
          { x: w, y: 0 },
          { x: w, y: -h },
          { x: w / 2, y: (-h * 3) / 2 },
          { x: 0, y: -h },
        ]
      var shapeSvg = parent
        .insert('polygon', ':first-child')
        .attr(
          'points',
          points
            .map(function (d) {
              return d.x + ',' + d.y
            })
            .join(' ')
        )
        .attr('transform', 'translate(' + -w / 2 + ',' + (h * 3) / 4 + ')')

      node.intersect = function (point) {
        return dagreD3.intersect.polygon(node, points, point)
      }

      return shapeSvg
    }
    // 自定义箭头
    render.arrows().hollowPoint = function normal(parent, id, edge, type) {
      var marker = parent
        .append('marker')
        .attr('id', id)
        .attr('viewBox', '0 0 10 10')
        .attr('refX', 9)
        .attr('refY', 5)
        .attr('markerUnits', 'strokeWidth')
        .attr('markerWidth', 8)
        .attr('markerHeight', 6)
        .attr('orient', 'auto')

      var path = marker
        .append('path')
        .attr('d', 'M 0 0 L 10 5 L 0 10 z')
        .style('stroke-width', 1)
        .style('stroke-dasharray', '1,0')
        .style('fill', '#fff')
        .style('stroke', '#333')
      dagreD3.util.applyStyle(path, edge[type + 'Style'])
    }

    render(inner, g)
  },
}
</script>

<style lang="less">
svg {
  font-size: 14px;
}

.node rect,
.node circle,
.node ellipse,
.node polygon {
  stroke: #333;
  fill: #fff;
  stroke-width: 1.5px;
}

.edgePath path {
  stroke: #606266;
  fill: #333;
  stroke-width: 1.5px;
}
</style>
}
